package com.ruicar.afs.cloud.manage.common.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.api.dto.BasicPaymentPoolDto;
import com.ruicar.afs.cloud.basic.api.dto.ContractStatusConditionDto;
import com.ruicar.afs.cloud.basic.api.dto.PaymentStatusConditionDto;
import com.ruicar.afs.cloud.basic.api.fegin.info.BasicInfoFeign;
import com.ruicar.afs.cloud.bizcommon.cms.dto.CmsResponse;
import com.ruicar.afs.cloud.bizcommon.cms.enums.CodeResponseEnum;
import com.ruicar.afs.cloud.bizcommon.cms.enums.SuccessResponseEnum;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.manage.cms.service.IcosToCmsChangeRepaymentService;
import com.ruicar.afs.cloud.manage.common.entity.ManageCancelRecord;
import com.ruicar.afs.cloud.manage.common.entity.ManageOverpaymentDifference;
import com.ruicar.afs.cloud.manage.common.mapper.ManageCancelRecordMapper;
import com.ruicar.afs.cloud.manage.common.service.ComAttachementFileService;
import com.ruicar.afs.cloud.manage.common.service.ManageCancelRecordService;
import com.ruicar.afs.cloud.manage.common.service.ManageOverpaymentDifferenceService;
import com.ruicar.afs.cloud.manage.common.util.CreatCaseNoUtil;
import com.ruicar.afs.cloud.manage.contractcancel.vo.ContractCancelManageVO;
import com.ruicar.afs.cloud.manage.finance.bankarrive.entity.ManageAccountRegister;
import com.ruicar.afs.cloud.manage.finance.bankarrive.service.ManageAccountRegisterService;
import com.ruicar.afs.cloud.manage.workflow.entity.WorkTaskCreatedInfo;
import com.ruicar.afs.cloud.manage.workflow.enums.NormalSubmitEnum;
import com.ruicar.afs.cloud.manage.workflow.enums.WorkflowTypeEnum;
import com.ruicar.afs.cloud.manage.workflow.processor.ContractWorkFlowSaveApproveInfoProcessor;
import com.ruicar.afs.cloud.manage.workflow.service.WorkTaskCreatedInfoService;
import com.ruicar.afs.cloud.manage.workflow.service.WorkflowSubmitService;
import com.ruicar.afs.cloud.manage.workflow.vo.TaskSubmitVO;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.StartFlowRequest;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author: Lee
 * @date 2020-05-30 04:45:15
 * @description
 */
@Slf4j
@Service
@AllArgsConstructor
public class ManageCancelRecordServiceImpl extends ServiceImpl<ManageCancelRecordMapper, ManageCancelRecord> implements ManageCancelRecordService {

    private final ManageOverpaymentDifferenceService manageOverpaymentDifferenceService;
    private final ContractWorkFlowSaveApproveInfoProcessor saveApproveInfoProcessor;
    private final ManageAccountRegisterService manageAccountRegisterService;
    private final ComAttachementFileService comAttachementFileService;
    private WorkTaskCreatedInfoService workTaskCreatedInfoService;
    private final WorkflowSubmitService workflowSubmitService;
    private final WorkflowService workflowService;
    private final BasicInfoFeign basicInfoFeign;
    private final IcosToCmsChangeRepaymentService icosToCmsChangeRepaymentService;
    @Override
    public void saveCancelRecord(ContractCancelManageVO manageCancelRecord) {

        //保存信息
        if (manageCancelRecord.getId() == null) {
            // 生成案件编号
            manageCancelRecord.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.cancelContract));
            //更改状态
            manageCancelRecord.setProcessStatus(ProcessStatusEnum.draft);
            manageCancelRecord.setApplyDate(DateUtil.date());
            manageCancelRecord.setApplyBy(SecurityUtils.getUser().getUserRealName());
            //原放款状态
            manageCancelRecord.setOldCreditStatus(manageCancelRecord.getCreditStatus());
            save(manageCancelRecord);
        } else {
            comAttachementFileService.saveFile(manageCancelRecord.getContractNo(), manageCancelRecord.getCaseNo(),
                    ContractBusinessEnum.cancelContract.name());
            comAttachementFileService.saveFile(manageCancelRecord.getContractNo(), manageCancelRecord.getCaseNo(),
                    ContractBusinessEnum.overpayment.name());
            updateById(manageCancelRecord);
        }
    }

    @Override
    public void submitCancelRecord(ContractCancelManageVO manageCancelRecord) {
        if (manageCancelRecord.getId() == null) {
            // 生成案件编号
            manageCancelRecord.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.cancelContract));
            comAttachementFileService.saveFile(manageCancelRecord.getContractNo(), manageCancelRecord.getCaseNo(),
                    ContractBusinessEnum.cancelContract.name());
            comAttachementFileService.saveFile(manageCancelRecord.getContractNo(), manageCancelRecord.getCaseNo(),
                    ContractBusinessEnum.overpayment.name());
            //更改状态
            manageCancelRecord.setProcessStatus(ProcessStatusEnum.draft);
            manageCancelRecord.setApplyDate(DateUtil.date());
            manageCancelRecord.setApplyBy(SecurityUtils.getUser().getUserRealName());
            //原放款状态
            manageCancelRecord.setOldCreditStatus(manageCancelRecord.getCreditStatus());
            save(manageCancelRecord);
        }
        //提交审核，发起流程
        if (ProcessStatusEnum.draft.equals(manageCancelRecord.getProcessStatus())) {
            manageCancelRecord.setProcessStatus(ProcessStatusEnum.underReview);
            manageCancelRecord.setId(manageCancelRecord.getId());
            //保存合同信息变更申请记录
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(manageCancelRecord, ContractBusinessEnum.cancelContract,
                    CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.CONTRACT_CANCEL);
            StartFlowRequest startFlowRequest = new StartFlowRequest();
            startFlowRequest.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.CONTRACT_CANCEL));
            startFlowRequest.setBizDataId(String.valueOf(manageCancelRecord.getId()));
            startFlowRequest.setFlowName((StringUtils.isEmpty(manageCancelRecord.getCustName()) ? "" : (manageCancelRecord.getCustName()) + "-") + AfsEnumUtil.desc(WorkflowTypeEnum.CONTRACT_CANCEL));
            String json = JSONObject.toJSONString(manageCancelRecord);
            JSONObject cancelJson = JSONObject.parseObject(json);
            //保存审批记录
            TaskSubmitVO vo = new TaskSubmitVO();
            vo.setBizData(cancelJson);
            workflowSubmitService.saveRecord(vo, AfsEnumUtil.desc(NormalSubmitEnum.SUGGEST_CHECK_FINAL));

            //更新放款状态
            if (PaymentStatusEnum.waitPayment.equals(manageCancelRecord.getCreditStatus())
                    || PaymentStatusEnum.failPayment.equals(manageCancelRecord.getCreditStatus())) {
                manageCancelRecord.setCreditStatus(PaymentStatusEnum.suspensionPayment);
                PaymentStatusConditionDto paymentStatus = new PaymentStatusConditionDto();
                paymentStatus.setContractNo(manageCancelRecord.getContractNo());
                paymentStatus.setPaymentStatus(PaymentStatusEnum.suspensionPayment);
                basicInfoFeign.updateStatus(paymentStatus);
            }
            updateById(manageCancelRecord);
            //开始流程
            workflowService.startWorkFlow(startFlowRequest, cancelJson);
        } else {
            //更新状态
            if (ProcessStatusEnum.payment.equals(manageCancelRecord.getProcessStatus())) {
                manageCancelRecord.setProcessStatus(ProcessStatusEnum.paymentUnderReview);
            } else if (ProcessStatusEnum.toBePaymentUnderReview.equals(manageCancelRecord.getProcessStatus())) {
                manageCancelRecord.setProcessStatus(ProcessStatusEnum.paymentUnderReview);
            } else if (ProcessStatusEnum.toBeRepaired.equals(manageCancelRecord.getProcessStatus())) {
                manageCancelRecord.setProcessStatus(ProcessStatusEnum.repairedUnderReview);
            }
            updateById(manageCancelRecord);
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(manageCancelRecord, ContractBusinessEnum.cancelContract,
                    CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.CONTRACT_CANCEL);
            //流程审批
            TaskSubmitVO vo = new TaskSubmitVO();
            String json = JSONObject.toJSONString(manageCancelRecord);
            JSONObject cancelJson = JSONObject.parseObject(json);
            vo.setBizData(cancelJson);
            vo.setApprovalOperating(manageCancelRecord.getApprovalOperating());
            vo.setApprovalOpinion(manageCancelRecord.getApprovalOpinion());
            vo.setReasonType(manageCancelRecord.getReasonType());
            workflowSubmitService.submit(vo);
        }
    }

    @Override
    public boolean saveProposalApplicationInfo(ContractCancelManageVO manageCancelRecord) {

        Boolean flag = false;

        CaseStatusEnum CaseStatus;
        ProcessStatusEnum processStatus;

        //来源
        manageCancelRecord.setBusinessSource(null);

        //更新处理状态
        if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_CHECK_FINAL).equals(manageCancelRecord.getApprovalOperating())) {
            //到账记录表状态改变
            if (EmptyUtils.isNotEmpty(manageCancelRecord.getAccountRegisterList())) {
                for (ManageAccountRegister manageAccountRegister : manageCancelRecord.getAccountRegisterList()) {
                    manageAccountRegisterService.update(Wrappers.<ManageAccountRegister>lambdaUpdate()
                            .eq(ManageAccountRegister::getId, manageAccountRegister.getId())
                            .set(ManageAccountRegister::getStatus, AccountRegistStatusEnum.ALREADY_GOUJI)
                            .set(ManageAccountRegister::getContractNo, manageCancelRecord.getContractNo()));
                }
            }
            WorkTaskCreatedInfo workTaskCreatedInfo = workTaskCreatedInfoService.getOne(Wrappers.<WorkTaskCreatedInfo>query().lambda()
                    .eq(WorkTaskCreatedInfo::getBizDataId, String.valueOf(manageCancelRecord.getId())));
            if (AfsEnumUtil.key(ProcessStatusEnum.approved).equals(workTaskCreatedInfo.getTaskMemo())) {
                manageCancelRecord.setEndDate(DateUtil.date());
                CaseStatus = CaseStatusEnum.APPROVED;
                processStatus = ProcessStatusEnum.approved;
                //更新合同状态
                ContractStatusConditionDto contractStatusDto = new ContractStatusConditionDto();
                contractStatusDto.setContractNo(manageCancelRecord.getContractNo());
                contractStatusDto.setContractStatus(ContractStatusEnum.contractCancel);
                if (DataSourceEnum.icos == manageCancelRecord.getDataSource()){
                    IResponse<Boolean> booleanIResponse = basicInfoFeign.updateContractStatus(contractStatusDto);
                    if (CommonConstants.FAIL.equals(booleanIResponse.getCode())) {
                        throw new AfsBaseException("合同取消结果数据推送至basic服务失败，请重试！");
                    }
                }else {
                    //向CMS更新合同状态
                    CmsResponse response = icosToCmsChangeRepaymentService.syncToCmsContractCancelResult(manageCancelRecord);
                    if (AfsEnumUtil.key(SuccessResponseEnum.FAIL).equals(response.getSuccess()) && !AfsEnumUtil.key(CodeResponseEnum.M10051).equals(response.getCode())) {
                        throw new AfsBaseException("合同取消结果数据推送至cms系统失败，请重试！");
                    }
                }

                manageCancelRecord.setProcessStatus(processStatus);
                manageCancelRecord.setContractStatus(ContractStatusEnum.contractCancel);
                //保存待办任务记录
                //保存合同信息变更申请记录
                saveApproveInfoProcessor.saveApproveInfo(manageCancelRecord, ContractBusinessEnum.cancelContract,
                        CaseStatus, BusinessUrlEnum.CONTRACT_CANCEL);
                flag = true;
                IResponse<BasicPaymentPoolDto> basicPaymentPool = basicInfoFeign.getPaymentPool(manageCancelRecord.getContractNo());
                //溢缴款数据
                BasicPaymentPoolDto dto = basicPaymentPool.getData();
                ManageOverpaymentDifference overpaymentDifference = new ManageOverpaymentDifference();
                BeanUtils.copyProperties(manageCancelRecord, overpaymentDifference, "id", "processStatus", "endDate");
                overpaymentDifference.setType(OverpaymentDifferenceTypeEnum.OVERPAYMENT);
                overpaymentDifference.setAmount(manageCancelRecord.getBalanceAmt());
                overpaymentDifference.setRequestDate(DateUtil.date());
                overpaymentDifference.setRefundAccount(dto.getReceiptAccount());
                overpaymentDifference.setBankName(dto.getReceiptBankCode());
                overpaymentDifference.setTermsPayment("线下");
                overpaymentDifference.setBranchBank(dto.getReceiptBankName());
                overpaymentDifference.setPayer(dto.getReceiptAccountName());
                overpaymentDifference.setBankNo(dto.getReceiptEbankCode());
                // 生成案件编号
                overpaymentDifference.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.overpayment));
                if (AmtHandleEnum.TAKE_BACK.equals(manageCancelRecord.getAmtHandle())) {

                    //溢缴款流程发起
                    overpaymentDifference.setProcessMode(ProcessModeEnum.refund);
                    overpaymentDifference.setProcessStatus(ProcessStatusEnum.underReview);
                    manageOverpaymentDifferenceService.save(overpaymentDifference);
                    //保存合同信息变更申请记录
                    //保存待办任务记录
                    saveApproveInfoProcessor.saveApproveInfo(overpaymentDifference, ContractBusinessEnum.overpayment,
                            CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.CONTRACT_CLOSE);
                    StartFlowRequest startFlowRequest = new StartFlowRequest();
                    startFlowRequest.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.CONTRACT_OVERPAYMENT));
                    startFlowRequest.setBizDataId(String.valueOf(overpaymentDifference.getId()));
                    startFlowRequest.setFlowName((StringUtils.isEmpty(overpaymentDifference.getCustName()) ? "" : (manageCancelRecord.getCustName()) + "-") + AfsEnumUtil.desc(WorkflowTypeEnum.CONTRACT_OVERPAYMENT));
                    String json = JSONObject.toJSONString(overpaymentDifference);
                    JSONObject cancelJson = JSONObject.parseObject(json);
                    //保存审批记录
                    TaskSubmitVO vo = new TaskSubmitVO();
                    vo.setBizData(cancelJson);
                    workflowSubmitService.saveRecord(vo, AfsEnumUtil.desc(NormalSubmitEnum.SUGGEST_CHECK_FINAL));
                    //开始流程
                    workflowService.startWorkFlow(startFlowRequest, cancelJson);
                } else {
                    //溢缴款流程发起
                    overpaymentDifference.setProcessMode(ProcessModeEnum.reduction);
                    overpaymentDifference.setProcessStatus(ProcessStatusEnum.approved);
                    manageOverpaymentDifferenceService.save(overpaymentDifference);
                }
            } else if (ProcessStatusEnum.end.name().equals(workTaskCreatedInfo.getTaskMemo()) &&
                    !PaymentStatusEnum.successPayment.equals(manageCancelRecord.getCreditStatus())) {
                manageCancelRecord.setEndDate(DateUtil.date());
                manageCancelRecord.setContractStatus(ContractStatusEnum.contractCancel);
                manageCancelRecord.setCreditStatus(PaymentStatusEnum.contractCancel);
                CaseStatus = CaseStatusEnum.APPROVED;
                processStatus = ProcessStatusEnum.approved;
                //更新合同状态
                ContractStatusConditionDto contractStatusDto = new ContractStatusConditionDto();
                contractStatusDto.setContractNo(manageCancelRecord.getContractNo());
                contractStatusDto.setContractStatus(ContractStatusEnum.contractCancel);
                if (DataSourceEnum.icos == manageCancelRecord.getDataSource()){
                    IResponse<Boolean> booleanIResponse = basicInfoFeign.updateContractStatus(contractStatusDto);
                    if (CommonConstants.FAIL.equals(booleanIResponse.getCode())) {
                        throw new AfsBaseException("还款日变更结果数据推送至basic服务失败，请重试！");
                    }
                }else {
                    //向CMS更新合同状态
                    CmsResponse response = icosToCmsChangeRepaymentService.syncToCmsContractCancelResult(manageCancelRecord);
                    if (AfsEnumUtil.key(SuccessResponseEnum.FAIL).equals(response.getSuccess()) && !AfsEnumUtil.key(CodeResponseEnum.M10051).equals(response.getCode())) {
                        throw new AfsBaseException("还款日变更结果数据推送至cms系统失败，请重试！");
                    }
                }

                //更新放款状态
                PaymentStatusConditionDto paymentStatus = new PaymentStatusConditionDto();
                paymentStatus.setContractNo(manageCancelRecord.getContractNo());
                paymentStatus.setPaymentStatus(PaymentStatusEnum.contractCancel);
                basicInfoFeign.updateStatus(paymentStatus);
                flag = true;
            } else if (ProcessStatusEnum.end.name().equals(workTaskCreatedInfo.getTaskMemo()) &&
                    PaymentStatusEnum.successPayment.equals(manageCancelRecord.getCreditStatus())) {
                CaseStatus = CaseStatusEnum.UNDER_REVIEW;
                processStatus = ProcessStatusEnum.payment;
            } else if (ProcessStatusEnum.payment.equals(manageCancelRecord.getProcessStatus())
                    || ProcessStatusEnum.paymentUnderReview.equals(manageCancelRecord.getProcessStatus())) {
                CaseStatus = CaseStatusEnum.UNDER_REVIEW;
                processStatus = ProcessStatusEnum.paymentUnderReview;
            } else if (ProcessStatusEnum.repairedUnderReview.equals(manageCancelRecord.getProcessStatus())) {
                CaseStatus = CaseStatusEnum.UNDER_REVIEW;
                processStatus = ProcessStatusEnum.repairedUnderReview;
            } else {
                CaseStatus = CaseStatusEnum.UNDER_REVIEW;
                processStatus = ProcessStatusEnum.underReview;
            }
            manageCancelRecord.setProcessStatus(processStatus);
            //保存待办任务记录
            //保存合同信息变更申请记录
            saveApproveInfoProcessor.saveApproveInfo(manageCancelRecord, ContractBusinessEnum.cancelContract,
                    CaseStatus, BusinessUrlEnum.CONTRACT_CANCEL);
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_REJECT_FINAL).equals(manageCancelRecord.getApprovalOperating())) {
            manageCancelRecord.setEndDate(DateUtil.date());
            manageCancelRecord.setProcessStatus(ProcessStatusEnum.refuse);
            //保存合同信息变更申请记录
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(manageCancelRecord, ContractBusinessEnum.cancelContract,
                    CaseStatusEnum.REFUSE, BusinessUrlEnum.CONTRACT_CANCEL);
            //到账记录表状态改变
            List<ManageAccountRegister> manageAccountRegisterList = manageAccountRegisterService.list(Wrappers.<ManageAccountRegister>lambdaUpdate()
                    .eq(ManageAccountRegister::getContractNo, manageCancelRecord.getContactNo()));
            if (EmptyUtils.isNotEmpty(manageAccountRegisterList)) {
                for (ManageAccountRegister manageAccountRegister : manageAccountRegisterList) {
                    manageAccountRegisterService.update(Wrappers.<ManageAccountRegister>lambdaUpdate()
                            .eq(ManageAccountRegister::getId, manageAccountRegister.getId())
                            .set(ManageAccountRegister::getStatus, AccountRegistStatusEnum.ALREADY_GENERA)
                            .set(ManageAccountRegister::getContractNo, null));
                }
            }
            //更新放款状态
            if (PaymentStatusEnum.suspensionPayment.equals(manageCancelRecord.getCreditStatus())) {
                manageCancelRecord.setCreditStatus(PaymentStatusEnum.waitPayment);
                PaymentStatusConditionDto paymentStatus = new PaymentStatusConditionDto();
                paymentStatus.setContractNo(manageCancelRecord.getContractNo());
                paymentStatus.setPaymentStatus(manageCancelRecord.getOldCreditStatus());
                basicInfoFeign.updateStatus(paymentStatus);
            }
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SEND_BACK).equals(manageCancelRecord.getApprovalOperating())) {
            WorkTaskCreatedInfo workTaskCreatedInfo = workTaskCreatedInfoService.getOne(Wrappers.<WorkTaskCreatedInfo>query().lambda()
                    .eq(WorkTaskCreatedInfo::getBizDataId, String.valueOf(manageCancelRecord.getId())));
            if (ProcessStatusEnum.toBePaymentUnderReview.name().equals(workTaskCreatedInfo.getTaskMemo())) {
                manageCancelRecord.setProcessStatus(ProcessStatusEnum.toBePaymentUnderReview);
            }
            if (ProcessStatusEnum.toBeRepaired.name().equals(workTaskCreatedInfo.getTaskMemo())) {
                manageCancelRecord.setProcessStatus(ProcessStatusEnum.toBeRepaired);
            }
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(manageCancelRecord, ContractBusinessEnum.cancelContract,
                    CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.CONTRACT_CANCEL);
        }
        updateById(manageCancelRecord);

        //流程审批
        TaskSubmitVO vo = new TaskSubmitVO();
        String json = JSONObject.toJSONString(manageCancelRecord);
        JSONObject cancelJson = JSONObject.parseObject(json);
        vo.setBizData(cancelJson);
        vo.setApprovalOperating(manageCancelRecord.getApprovalOperating());
        vo.setApprovalOpinion(manageCancelRecord.getApprovalOpinion());
        vo.setReasonType(manageCancelRecord.getReasonType());
        workflowSubmitService.submit(vo);
        return flag;
    }

    @Override
    public IPage getContractCancelList(Page page, ContractCancelManageVO vo) {
        return this.baseMapper.getContractCancelList(page, vo);
    }
}
